﻿using Kimd.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace Kimd.Motion
{
    public class MotionLimit
    {
        public static Dictionary<string, Axis> MachineAxis;
        public static Dictionary<string, Sensor> MachineSensor;
        private Axis _thisAxis;
        public LimitType LimitType { get; set; }
        public string LimitAxisName { get; set; }
        public string LimitSensorName { get; set; }
        public double Position { get; set; }
        public double LowPosition { get; set; }
        public double HighPosition { get; set; }
        public bool IsSensed { get; set; }
        [XmlIgnore]
        public bool IsEnable { get; set; } = true;

        public MotionLimit()
        {

        }
        public void SetAxis(Axis axis)
        {
            this._thisAxis = axis;
        }
        public MotionLimit(LimitType limitType, string limitAxisName, double position, double lowPosition, double highPosition)
            : this()
        {
            this.LimitType = limitType;
            this.LimitAxisName = limitAxisName;
            this.Position = position;
            this.LowPosition = lowPosition;
            this.HighPosition = highPosition;
            this.IsEnable = true;
        }
        public MotionLimit(LimitType limitType, string limitSensorName, bool isSensed)
            : this()
        {
            this.LimitType = limitType;
            this.LimitSensorName = limitSensorName;
            this.IsSensed = isSensed;   
            this.IsEnable = true;
        }
        public static void Init(Dictionary<string, Axis> machineAxis, Dictionary<string, Sensor> machineSensor)
        {
            MachineAxis = machineAxis;
            MachineSensor = machineSensor;
        }

        public bool IsBreakRule(bool posDirection, out string errInfo)
        {
            errInfo = "";
            if (!this.IsEnable)
                return false;
            switch(LimitType)
            {
                case LimitType.SoftPositiveLimit:
                case LimitType.SoftNegativeLimit:
                case LimitType.NotMoving:
                case LimitType.AxisInPosition:
                case LimitType.AxisMoreThanPosition:
                case LimitType.AxisLessThanPosition:
                case LimitType.AxisBetweenPosition:
                case LimitType.AxisBeyondPosition:
                    if (string.IsNullOrEmpty(LimitAxisName))
                    {
                        errInfo = "轴限制条件设置错误!限制轴未设置";
                        return true;
                    }
                    if (!MachineAxis.ContainsKey(LimitAxisName))
                    {
                        errInfo = "轴限制条件设置错误!限制轴不存在";
                        return true;
                    }
                    break;
                case LimitType.SensorNotSensed:
                case LimitType.SensorSensed:
                    if (string.IsNullOrEmpty(LimitSensorName))
                    {
                        errInfo = "轴限制条件设置错误!限制感应器未设置";
                        return true;
                    }
                    if (!MachineSensor.ContainsKey(LimitSensorName))
                    {
                        errInfo = "轴限制条件设置错误!限制感应器不存在";
                        return true;
                    }
                    break;
            }
            switch (LimitType)
            {
                case LimitType.SoftPositiveLimit:
                    errInfo = "超出正向软限位";
                    return posDirection && MachineAxis[LimitAxisName].Position > Position;
                case LimitType.SoftNegativeLimit:
                    errInfo = "超出负向软限位";
                    return !posDirection && MachineAxis[LimitAxisName].Position < Position;
                case LimitType.NotMoving:
                    errInfo = $"轴{LimitAxisName}不在Ready状态中";
                    return !MachineAxis[LimitAxisName].Ready;
                case LimitType.AxisInPosition:
                    errInfo = $"轴{LimitAxisName}不在某个位置:[{Position}]";
                    return Math.Abs(MachineAxis[LimitAxisName].Position - Position) > 0.1;
                case LimitType.AxisMoreThanPosition:
                    errInfo = $"轴{LimitAxisName}大于某个位置:[{Position}]";
                    return MachineAxis[LimitAxisName].Position <= Position;
                case LimitType.AxisLessThanPosition:
                    errInfo = $"轴{LimitAxisName}小于某个位置:[{Position}]";
                    return MachineAxis[LimitAxisName].Position > Position;
                case LimitType.AxisBetweenPosition:
                    errInfo = $"轴{LimitAxisName}在区间之内:[{LowPosition}]-[{HighPosition}]";
                    return MachineAxis[LimitAxisName].Position < LowPosition || MachineAxis[LimitAxisName].Position > HighPosition;
                case LimitType.AxisBeyondPosition:
                    errInfo = $"轴{LimitAxisName}在区间之外:[{LowPosition}]-[{HighPosition}]";
                    return MachineAxis[LimitAxisName].Position >= LowPosition && MachineAxis[LimitAxisName].Position <= HighPosition;
                case LimitType.SensorSensed:
                    errInfo = $"感应器{LimitSensorName}感应到";
                    return !MachineSensor[LimitSensorName].WaitOn();
                case LimitType.SensorNotSensed:
                    errInfo = $"感应器{LimitSensorName}未感应到";
                    return MachineSensor[LimitSensorName].WaitOn();
            }
            return false;
        }
    }

    public enum LimitType
    {
        [Description("正向软限位")]
        SoftPositiveLimit,
        [Description("负向软限位")]
        SoftNegativeLimit,
        [Description("不能移动")]
        NotMoving,
        [Description("在某个位置")]
        AxisInPosition,
        [Description("大于某个位置")]
        AxisMoreThanPosition,
        [Description("小于某个位置")]
        AxisLessThanPosition,
        [Description("位于两个位置之间")]
        AxisBetweenPosition,
        [Description("不在两个位置之间")]
        AxisBeyondPosition,
        [Description("感应到")]
        SensorSensed,
        [Description("感应不到")]
        SensorNotSensed,
    }
}
